﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace GDI_应用案例.Pages.Controls
{
    public class MobileVerificationCode : IDisposable
    {
        static readonly Dictionary<Shape, IShape> _shapeCache;
        static MobileVerificationCode()
        {
            Assembly currentAssembly = Assembly.GetExecutingAssembly();
            Type commonType = typeof(IShape);
            Type[] allTypes = currentAssembly.GetTypes().Where(t => commonType.IsAssignableFrom(t) && t.IsClass).ToArray();
            List<IShape> shapes = new List<IShape>(allTypes.Length);
            foreach (var item in allTypes)
            {
                shapes.Add((IShape)Activator.CreateInstance(item));
            }
            _shapeCache = shapes.ToDictionary(t => t.Shape, t => t);
        }
        public MobileVerificationCode()
        {
            Shape = Shape.Love;
        }
        private Bitmap _image;
        private readonly string[] _imageExtensions = { ".jpg", ".jpeg", ".png" };
        private Shape _shapeEnum;
        private IShape _shape;
        private int _radius = 10;
        private readonly Random _random = new Random();
        public Shape Shape
        {
            get => _shapeEnum;
            set
            {
                _shapeEnum = value;
                _shape = _shapeCache[value];
            }
        }
        public int Radius
        {
            get => _radius;
            set
            {
                value = Math.Max(value, 0);
            }
        }
        public void SetImage(string filePath)
        {
            if (!File.Exists(filePath))
                throw new FileNotFoundException("此图像文件不存在");
            string extension = Path.GetExtension(filePath)?.ToLower();
            if (!_imageExtensions.Any(x => x == extension))
                throw new ArgumentException($"只支持 {string.Join(",", _imageExtensions)} 文件");

            SetImage(new Bitmap(filePath));
        }
        public void SetImage(Bitmap image)
        {
            _image?.Dispose();
            _image = image;
        }

        public MobileVerificationCodeResult Create()
        {
            Bitmap bitmap= _image.Clone() as Bitmap;
            Graphics g = Graphics.FromImage(bitmap);
            g.Smooth();
            GraphicsPath path = _shape.CreatePath(bitmap.Width, bitmap.Height, Radius, _random);
            // 绘制图像
            g.DrawImage(bitmap, 0, 0);
            // 绘制形状
            //DrawShape(path,g,bitmap);
            Brush brush=new SolidBrush(Color.FromArgb(150,Color.Black));
            g.FillPath(brush,path);
            brush.Dispose();

            path.Dispose();
            g.Dispose();

            return new MobileVerificationCodeResult
            {
                Bitmap = bitmap,
            };
        }
        private void DrawShape(GraphicsPath path,Graphics g, Bitmap bitmap)
        {
            // 使用反向渐变填充模拟凹陷效果
            using (Brush gradientBrush = new PathGradientBrush(path))
            {
                // 设置中心颜色（较深）
                ((PathGradientBrush)gradientBrush).CenterColor = Color.FromArgb(150, Color.Black);

                // 设置边缘颜色（较浅）
                Color[] surroundColors = { Color.FromArgb(30, Color.Black) };
                ((PathGradientBrush)gradientBrush).SurroundColors = surroundColors;

                // 填充路径
                g.FillPath(gradientBrush, path);
            }

            // 添加内阴影效果
            using (GraphicsPath innerShadowPath = (GraphicsPath)path.Clone())
            {
                // 缩小路径以模拟内阴影
                using (Matrix matrix = new Matrix())
                {
                    matrix.Translate(2, 2); // 向内偏移
                    innerShadowPath.Transform(matrix);
                }

                using (Brush shadowBrush = new SolidBrush(Color.FromArgb(100, Color.Black)))
                {
                    g.FillPath(shadowBrush, innerShadowPath); // 填充内阴影
                }
            }

            // 添加边缘暗化效果
            using (Pen edgePen = new Pen(Color.FromArgb(150, Color.Black), 8))
            {
                g.DrawPath(edgePen, path); // 绘制边缘暗化线条
            }
        }
        public void Dispose()
        {
            _image?.Dispose();
        }
        ~MobileVerificationCode()
        {
            Dispose();
        }
    }
    public class MobileVerificationCodeResult
    {
        public Bitmap Bitmap { get; set; }
    }
    public enum Shape
    {
        Pie,
        RoundedRectangle,
        RoundedStar,
        RoundedTriangle,
        ConcaveConvexRectangle,
        Hexagon,
        Love
    }
    public interface IShape
    {
        GraphicsPath CreatePath(int width, int height, int cornerRadius, Random random);
        Shape Shape { get; }
    }
    public class PieShape : IShape
    {
        public Shape Shape => Shape.Pie;

        public GraphicsPath CreatePath(int width, int height, int cornerRadius, Random random)
        {
            GraphicsPath path = new GraphicsPath();
            int w = width >> 1;
            int h = height >> 1;
            path.AddPie(50, 50, w, h, 45, 90); // 起始角度45度，扫过90度
            return path;
        }
    }
    public class RoundedRectangleShape : IShape
    {
        public GraphicsPath CreatePath(int width, int height, int cornerRadius, Random random)
        {
            GraphicsPath path = new GraphicsPath();
            Rectangle rect = new Rectangle(50, 50, 200, 100);
            path.AddArc(rect.X, rect.Y, cornerRadius, cornerRadius, 180, 90);
            path.AddArc(rect.Right - cornerRadius, rect.Y, cornerRadius, cornerRadius, 270, 90);
            path.AddArc(rect.Right - cornerRadius, rect.Bottom - cornerRadius, cornerRadius, cornerRadius, 0, 90);
            path.AddArc(rect.X, rect.Bottom - cornerRadius, cornerRadius, cornerRadius, 90, 90);
            path.CloseFigure();
            return path;
        }

        public Shape Shape => Shape.RoundedRectangle;
    }
    public class RoundedStarShape : IShape
    {
        public Shape Shape => Shape.RoundedStar;
        public GraphicsPath CreatePath(int width, int height, int cornerRadius, Random random)
        {
            GraphicsPath path = new GraphicsPath();
            int numPoints = 5;
            double angleIncrement = Math.PI / numPoints; // 每个点之间的角度增量
            double startAngle = -Math.PI / 2; // 从顶部开始

            PointF[] points = new PointF[numPoints * 2];
            int outerRadius = cornerRadius;
            int innerRadius = outerRadius >> 1;
            Point center = new Point();
            // 计算星形的所有顶点
            for (int i = 0; i < numPoints * 2; i++)
            {
                double angle = startAngle + i * angleIncrement;
                int radius = i % 2 == 0 ? outerRadius : innerRadius;
                points[i] = new PointF(
                    center.X + (float)(radius * Math.Cos(angle)),
                    center.Y + (float)(radius * Math.Sin(angle))
                );
            }

            // 绘制圆角星形的路径
            for (int i = 0; i < points.Length; i++)
            {
                PointF currentPoint = points[i];
                PointF nextPoint = points[(i + 1) % points.Length];

                // 添加直线
                path.AddLine(currentPoint, nextPoint);

                // 添加圆角
                if (cornerRadius > 0)
                {
                    PointF cornerCenter = nextPoint;
                    RectangleF cornerRect = new RectangleF(
                        cornerCenter.X - cornerRadius,
                        cornerCenter.Y - cornerRadius,
                        cornerRadius * 2,
                        cornerRadius * 2
                    );

                    float startAngleDeg = (float)(Math.Atan2(currentPoint.Y - cornerCenter.Y, currentPoint.X - cornerCenter.X) * 180 / Math.PI);
                    float sweepAngleDeg = (float)(Math.Atan2(nextPoint.Y - cornerCenter.Y, nextPoint.X - cornerCenter.X) * 180 / Math.PI - startAngleDeg);

                    path.AddArc(cornerRect, startAngleDeg, sweepAngleDeg);
                }
            }

            path.CloseFigure();
            return path;
        }
        // 获取圆角的矩形区域
        private RectangleF GetCornerRectangle(Point center, int radius)
        {
            return new RectangleF(center.X - radius, center.Y - radius, radius * 2, radius * 2);
        }

        // 获取两个点之间的角度
        private float GetAngle(Point p1, Point p2)
        {
            return (float)(Math.Atan2(p2.Y - p1.Y, p2.X - p1.X) * 180 / Math.PI);
        }

        // 获取圆角的边缘点
        private PointF GetEdgePoint(Point p1, Point p2, int radius)
        {
            float angle = (float)(Math.Atan2(p2.Y - p1.Y, p2.X - p1.X));
            return new PointF(p1.X + radius * (float)Math.Cos(angle), p1.Y + radius * (float)Math.Sin(angle));
        }

    }
    public class RoundedTriangleShape : IShape
    {
        public Shape Shape => Shape.RoundedTriangle;
        public GraphicsPath CreatePath(int width, int height, int cornerRadius, Random random)
        {
            GraphicsPath path = new GraphicsPath();

            // 确定等边三角形的大小
            int triangleSize = Math.Min(width, height) / 3; // 三角形的边长
            int triangleHeight = (int)(triangleSize * Math.Sqrt(3) / 2); // 等边三角形的高度

            // 随机生成三角形在右边区域的位置
            int maxX = width - triangleSize - cornerRadius; // 最大X坐标，确保不超出边界
            int minX = width >> 1; // 最小X坐标，确保在右边区域
            int x = random.Next(minX, maxX); // 随机X坐标

            int y = height - triangleHeight >> 1; // 使三角形在高度上居中

            // 等边三角形的三个顶点
            Point p1 = new Point(x + (triangleSize >> 1), y); // 顶角在正上方
            Point p2 = new Point(x, y + triangleHeight); // 左下角
            Point p3 = new Point(x + triangleSize, y + triangleHeight); // 右下角

            // 计算圆角的边缘点
            PointF edge1 = GetEdgePoint(p1, p2, cornerRadius);
            PointF edge2 = GetEdgePoint(p2, p1, cornerRadius);
            PointF edge3 = GetEdgePoint(p2, p3, cornerRadius);
            PointF edge4 = GetEdgePoint(p3, p2, cornerRadius);
            PointF edge5 = GetEdgePoint(p3, p1, cornerRadius);
            PointF edge6 = GetEdgePoint(p1, p3, cornerRadius);

            // 绘制圆角等边三角形的路径
            path.AddLine(edge1, edge2); // 第一条边
            path.AddArc(GetCornerRectangle(p2, cornerRadius), GetAngle(p2, p1) - 90, 60); // 第一个圆角
            path.AddLine(edge3, edge4); // 第二条边
            path.AddArc(GetCornerRectangle(p3, cornerRadius), GetAngle(p3, p2) - 90, 60); // 第二个圆角
            path.AddLine(edge5, edge6); // 第三条边
            path.AddArc(GetCornerRectangle(p1, cornerRadius), GetAngle(p1, p3) - 90, 60); // 第三个圆角
            path.CloseFigure();

            return path;
        }

        // 获取圆角的矩形区域
        private RectangleF GetCornerRectangle(Point center, int radius)
        {
            return new RectangleF(center.X - radius, center.Y - radius, radius * 2, radius * 2);
        }

        // 获取两个点之间的角度
        private float GetAngle(Point p1, Point p2)
        {
            return (float)(Math.Atan2(p2.Y - p1.Y, p2.X - p1.X) * 180 / Math.PI);
        }

        // 获取圆角的边缘点
        private PointF GetEdgePoint(Point p1, Point p2, int radius)
        {
            float angle = (float)(Math.Atan2(p2.Y - p1.Y, p2.X - p1.X));
            return new PointF(p1.X + radius * (float)Math.Cos(angle), p1.Y + radius * (float)Math.Sin(angle));
        }
    }
    public class ConcaveConvexRectangleShape : IShape
    {
        public Shape Shape => Shape.ConcaveConvexRectangle;
        public GraphicsPath CreatePath(int width, int height, int cornerRadius, Random random)
        {
            GraphicsPath path = new GraphicsPath();
            int x = 0, y = 0;
            int tabSize = 10;
            // 定义圆角矩形的基本路径
            path.AddArc(x, y, cornerRadius * 2, cornerRadius * 2, 180, 90); // 左上角
            path.AddArc(x + width - cornerRadius * 2, y, cornerRadius * 2, cornerRadius * 2, 270, 90); // 右上角
            path.AddArc(x + width - cornerRadius * 2, y + height - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 0, 90); // 右下角
            path.AddArc(x, y + height - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 90, 90); // 左下角
            path.CloseFigure();

            // 添加凸出的缺口（顶部）
            path.AddLine(x + width / 2 - tabSize, y, x + width / 2 - tabSize, y - tabSize);
            path.AddLine(x + width / 2 - tabSize, y - tabSize, x + width / 2 + tabSize, y - tabSize);
            path.AddLine(x + width / 2 + tabSize, y - tabSize, x + width / 2 + tabSize, y);

            // 添加凹陷的缺口（底部）
            path.AddLine(x + width / 2 - tabSize, y + height, x + width / 2 - tabSize, y + height + tabSize);
            path.AddLine(x + width / 2 - tabSize, y + height + tabSize, x + width / 2 + tabSize, y + height + tabSize);
            path.AddLine(x + width / 2 + tabSize, y + height + tabSize, x + width / 2 + tabSize, y + height);

            return path;
        }
    }
    public class HexagonShape : IShape
    {
        public Shape Shape => Shape.Hexagon;
        public GraphicsPath CreatePath(int width, int height, int cornerRadius, Random random)
        {
            GraphicsPath path = new GraphicsPath();

           

            return path;
        }
    }
    public class LoveShape : IShape
    {
        public Shape Shape => Shape.Love;
        public GraphicsPath CreatePath(int width, int height, int cornerRadius, Random random)
        {
            GraphicsPath path = new GraphicsPath();

            // 定义爱心的基本参数
            int margin = 20; // 边距，确保爱心不超出边界
            int heartWidth = (width - 2 * margin) / 2; // 爱心的宽度，确保不超过图像宽度
            int heartHeight = (height - 2 * margin) / 2; // 爱心的高度，确保不超过图像高度

            // 计算爱心的位置
            int heartX = width - heartWidth - margin; // 爱心位于图像的右边，留出边距
            int heartY = (height - heartHeight) / 2; // 爱心垂直居中

            // 使用数学公式绘制爱心
            int numPoints = 100; // 爱心曲线的点数
            PointF[] points = new PointF[numPoints];

            for (int i = 0; i < numPoints; i++)
            {
                // 参数化方程生成爱心形状
                double t = 2 * Math.PI * i / numPoints;
                double x = 16 * Math.Pow(Math.Sin(t), 3);
                double y = 13 * Math.Cos(t) - 5 * Math.Cos(2 * t) - 2 * Math.Cos(3 * t) - Math.Cos(4 * t);

                // 缩放并平移爱心到指定位置
                float scaledX = (float)(x * heartWidth / 20) + heartX + heartWidth / 2;
                float scaledY = (float)(-y * heartHeight / 20) + heartY + heartHeight / 2;

                // 使用自定义的 Clamp 方法确保爱心不超出边界
                scaledX = Clamp(scaledX, margin, width - margin);
                scaledY = Clamp(scaledY, margin, height - margin);

                points[i] = new PointF(scaledX, scaledY);
            }

            // 将点添加到路径中
            path.AddCurve(points);
            path.CloseFigure(); // 闭合路径

            return path;
        }
        // 自定义 Clamp 方法
        private float Clamp(float value, float min, float max)
        {
            if (value < min)
                return min;
            if (value > max)
                return max;
            return value;
        }
    }
}
